﻿using System;
using System.Collections.Generic;
using System.Threading;

namespace IFramework
{
    public class MyThread : IThread, IPoolObj, IObserver
    {
        public Type ObjType
        {
            get
            {
                return typeof(Thread);
            }
        }

        public object GetContent()
        {
            return thread;
        }

        private void Run()
        {
            this.eve.Set();
            isRunning = true;
        }
        private void Stop()
        {
            if (pool.Count != 0) return;
            this.eve.Reset();
            isRunning = false;
        }
        private ManualResetEvent eve = new ManualResetEvent(false);//为trur,一开始就可以执行
        private Queue<ThreadTaskBox> pool = new Queue<ThreadTaskBox>();
        private List<ThreadTaskBox> runningPool = new List<ThreadTaskBox>();
        public bool IsRunning { get { return isRunning; } }
        private bool isRunning;
        private Thread thread;
        public Thread Thread
        {
            get
            {
                return thread;
            }
        }

        public object Content
        {
            get
            {
                throw new NotImplementedException();
            }
        }

        public void RunTask(ThreadTaskBox[] boxes)
        {
            if (!isRunning)
            {
                Run();
            }
            lock (pool)
            {
                for (int i = 0; i < boxes.Length; i++)
                {
                    pool.Enqueue(boxes[i]);
                }
            }
        }
        public void RunTask(ThreadTaskBox box)
        {
            if (!isRunning)
            {
                Run();
            }
            pool.Enqueue(box);
        }
        private void RunTask()
        {
            while (true)
            {
                this.eve.WaitOne();
                lock (pool)
                {
                    runningPool.Clear();
                    runningPool.AddRange(pool);
                    pool.Clear();
                }
                for (int i = 0; i < runningPool.Count; i++)
                {
                    ThreadTaskBox box = runningPool[i];
                    runningPool.RemoveAt(i);
                    box.Action();
                    box.CallBack();
                    PoolManager.Instance.Restore(typeof(ThreadTaskBox), box);
                }
                lock (pool)
                {
                    if (pool.Count == 0)
                    {
                        ObserveManager.Instance.Notify(null, this, 0, this);
                    }
                }
            }
        }
        public void Listen(EventArgs args, Type eventType, int code, params object[] message)
        {
            if ((message[0] as MyThread) != this) return;
            PoolManager.Instance.Restore(typeof(MyThread), this);
        }
        public void OnCreate(params object[] paras)
        {
            thread = new Thread(RunTask);
            thread.IsBackground = true;
            thread.Start();
            ObserveManager.Instance.AddObserver(this, this);
        }
        public void OnReuse(params object[] paras)
        {
            Run();
        }
        public void OnRestore(params object[] paras)
        {
            Stop();
        }
        public void OnClean(params object[] paras)
        {
            thread.Abort();
            ObserveManager.Instance.RemoveObserver(this, this);
            thread = null;
        }
    }
}